#include "SharedMemory.h"
#include"protocol.h"

int SharedMemory::loginNumber = 0;

SharedMemory::SharedMemory(int write_fd)
{
	// 1. 创建信号量
	sem_shm = sem_create((key_t)40001, 1);   // key=40001

	// 2. 初始化信号量值
	sem_setval(sem_shm, 0, 1);   // 初始值=1（可用）

	this->write_fd = write_fd;
	// 创建共享内存
	shmid = shmget((key_t)20001, sizeof(ShmControl), IPC_CREAT | 0666);
	ShmControl* shm = (ShmControl*)shmat(shmid, NULL, 0);

	// 初始化内存
	for (int i = 0; i < MEMORYNUMBER; i++) {
		shm->blocks[i].index = i;
		shm->blocks[i].status = 0;
		memset(shm->blocks[i].data, 0, sizeof(shm->blocks[i].data));
	}
	// 分离共享内存
	shmdt(shm);
	// 创建消息队列
	msgidA = msgget((key_t)111111, IPC_CREAT | 0666);
	if (msgidA == -1) {
		perror("msgget A failed");
		// 可能需要清理之前创建的资源
		throw std::runtime_error("Failed to create message queue A");
	}

	msgidB = msgget((key_t)222222, IPC_CREAT | 0666);
	if (msgidB == -1) {
		perror("msgget B failed");
		// 清理msgidA
		msgctl(msgidA, IPC_RMID, NULL);
		throw std::runtime_error("Failed to create message queue B");
	}
}

SharedMemory::~SharedMemory()
{
	shmctl(shmid, IPC_RMID, NULL);//销毁共享内存
	delete shmaddr;
}

void SharedMemory::CreateThread()
{
	pthread_t t;
	//创建读取共享数据线程
	pthread_create(&t, NULL, client_handle, this);

}

bool SharedMemory::Front_write(const HEAD& head, const char* body, int client_fd) 
{
	stringstream logMsg;
	logMsg << "有效连接数：" << TcpServer::client_states.size()
		<< "\n服务类型：" << head.service_type
		<< "\n接收数据包大小：" << head.data_len;

	string messages = logMsg.str();
	write(write_fd, messages.c_str(), messages.size());

	if (head.service_type <= 0 || head.data_len < 0) {
		return false;
	}

	// 获取共享内存
	ShmControl* shm = (ShmControl*)shmat(shmid, NULL, 0);
	if (shm == (void*)-1) {
		cerr << "共享内存连接失败: " << strerror(errno) << endl;
		return false;
	}

	int index = -1;
	// 寻找空闲块（加锁保护）
	sem_p(sem_shm, 0); // P操作
	try {
		// 寻找空闲块
		for (int i = 0; i < MEMORYNUMBER; i++) {
			if (shm->blocks[i].status == 0) {
				index = i;
				break;
			}
		}

		if (index == -1) {
			sem_v(sem_shm, 0); // 释放锁
			shmdt(shm);
			cout << "无空闲块，等待重试..." << endl;
			usleep(100000);
			return false;
		}

		// 准备缓冲区
		std::vector<char> buf(MEMORYSIZE, 0);
		memcpy(buf.data(), &head, sizeof(HEAD));
		memcpy(buf.data() + sizeof(HEAD), body, head.data_len);

		// 写入共享内存
		ShmBlock* block = &shm->blocks[index];
		memcpy(block->data, buf.data(), sizeof(block->data));
		block->status = 1; // 标记为已写入

		// 准备消息
		MSG msg = { 0 };
		msg.index = index;
		msg.client_fd = client_fd;
		msg.mtype = 1;

		// 发送消息
		if (msgsnd(msgidA, &msg, sizeof(MSG) - sizeof(long), IPC_NOWAIT) == -1) {
			throw std::runtime_error(string("消息发送失败: ") + strerror(errno));
		}
		sem_v(sem_shm, 0); // V操作
		shmdt(shm);
		return true;
	}
	catch (const exception& e) {
		sem_v(sem_shm, 0); // 确保异常时释放锁
		shmdt(shm);
		cerr << "写入异常: " << e.what() << endl;
		return false;
	}
}

void* SharedMemory::client_handle(void* arg) {
	SharedMemory* info = (SharedMemory*)arg;
	char date[MEMORYSIZE] = { 0 };
	HEAD head = { 0 };
	MSG msg = { 0 };
	char message[64] = { 0 };
	while (true) {
		try {
			bzero(message, sizeof(message));
			// 接收消息
			if (msgrcv(info->msgidB, &msg, sizeof(MSG), 1, 0) == -1) {
				if (errno != EINTR) {
					cerr << "消息接收失败: " << strerror(errno) << endl;
				}
				continue;
			}

			// 获取共享内存（加锁）
			ShmControl* shm = (ShmControl*)shmat(info->shmid, NULL, 0);
			if (shm == (void*)-1) {
				throw std::runtime_error(string("共享内存连接失败: ") + strerror(errno));
			}

			info->sem_p(info->sem_shm, 0); // P操作

			// 读取数据块
			ShmBlock* block = &shm->blocks[msg.index];
			memcpy(date, block->data, sizeof(block->data));
			block->status = 0; // 标记为空闲

			info->sem_v(info->sem_shm, 0); // V操作

			// 处理包头
			memcpy(&head, date, sizeof(HEAD));

			//判断业务类型
			if (head.service_type == SMS_CODE || head.service_type == REGISTER ||
				head.service_type == SAVEVIDEO || head.service_type == IMGUPLOAD ||
				head.service_type == VIDEOUPLOAD || head.service_type == DELETEVIDEO)
			{
				RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(RESP));
				memcpy(message, res.message, sizeof(message));
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(RESP));
			}
			else if (head.service_type == GV_CODE)
			{
				GV_CODE_RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(GV_CODE_RESP));
				memcpy(message, res.message, sizeof(message));
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(GV_CODE_RESP));
			}
			else if (head.service_type == LOGIN)
			{
				LOGIN_RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(LOGIN_RESP));
				memcpy(message, res.message, sizeof(message));
				if (res.status_code == Success)
				{
					//更新为登录状态
					TcpServer::client_states[msg.client_fd].isLogin = true;
					//增加登录人数
					loginNumber++;
					//移出心跳
				}
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(LOGIN_RESP));
			}
			else if (head.service_type == GETVIDOE)
			{
				GETVIDEO_RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(GETVIDEO_RESP));
				memcpy(message, res.message, sizeof(message));
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(GETVIDEO_RESP));
			}
			else if (head.service_type == GETIMG)
			{
				GETIMG_RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(GETIMG_RESP));
				memcpy(message, res.message, sizeof(message));
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(GETIMG_RESP));
			}
			else if (head.service_type == OVERIMG)
			{
				SAVEIMG_RESP res = { 0 };
				memcpy(&res, date + sizeof(HEAD), sizeof(SAVEIMG_RESP));
				memcpy(message, res.message, sizeof(message));
				write(msg.client_fd, date, sizeof(HEAD) + sizeof(SAVEIMG_RESP));
			}
			else if (head.service_type == HEART)
			{
				write(msg.client_fd, date, sizeof(HEAD));
			}

			// 日志记录
			stringstream logMsg;
			logMsg << "发送数据包大小:  " << head.data_len
				<< "\n登录人数：" << loginNumber
				<< "\n" << message
				<< "\n---------------------" << endl;
			string messages = logMsg.str(); //转为字符串类型
			write(info->write_fd, messages.c_str(), messages.size()); // 发送到日志进程

			shmdt(shm);
		}
		catch (const exception& e)
		{
			cerr << "处理异常: " << e.what() << endl;
			info->sem_v(info->sem_shm, 0); // 确保异常时释放锁
		}
	}
	return nullptr;
}

int SharedMemory::sem_create(key_t key, int num_sems) {
	int semid = semget(key, num_sems, IPC_CREAT | 0666);
	if (semid == -1) {
		perror("semget failed");
		throw std::runtime_error("信号量创建失败");
	}
	return semid;
}

int SharedMemory::sem_setval(int semid, int semindex, int val) {
	union semun arg;
	arg.val = val;
	if (semctl(semid, semindex, SETVAL, arg) == -1) {
		perror("semctl SETVAL failed");
		return -1;
	}
	return 0;
}

int SharedMemory::sem_p(int semid, int semindex) {
	struct sembuf buf = { semindex, -1, SEM_UNDO };
	if (semop(semid, &buf, 1) == -1) {
		perror("semop P failed");
		return -1;
	}
	return 0;
}

int SharedMemory::sem_v(int semid, int semindex) {
	struct sembuf buf = { semindex, 1, SEM_UNDO };
	if (semop(semid, &buf, 1) == -1) {
		perror("semop V failed");
		return -1;
	}
	return 0;
}
